package com.ztewatch.wearcontacts.service;

import java.io.IOException;
import java.util.ArrayList;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;

import android.app.Service;
import android.content.ContentProviderOperation;
import android.content.ContentProviderResult;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.Context;
import android.content.Intent;
import android.content.OperationApplicationException;
import android.content.SharedPreferences;
import android.content.res.XmlResourceParser;
import android.os.IBinder;
import android.os.RemoteException;
import android.provider.ContactsContract;
import android.provider.ContactsContract.CommonDataKinds.GroupMembership;
import android.provider.ContactsContract.CommonDataKinds.Phone;
import android.provider.ContactsContract.Groups;
import android.text.TextUtils;
import android.util.Log;

import com.ztewatch.wearcontacts.R;
import com.ztewatch.wearcontacts.data.DefaultContactInfo;
import com.ztewatch.wearcontacts.utils.WeakAsyncTask;

public class LoadGroupService extends Service {
	private Context context;

	private final static String TAG = "LoadGroupService";
	public final static String GROUPSBOOTRECEIVER = "GROUPSBOOTRECEIVER";
	private static int STATE_UNIMPORTED = 0;
	private static int STATE_IMPORTING = -1;
	private final static String GROUP_STATUS = "GROUP_STATUS";

	@Override
	public void onCreate() {
		super.onCreate();
		context = getBaseContext();
		Log.e(TAG, "LoadGroupService execute");
		LoadGroupsContactsTask task = new LoadGroupsContactsTask(context);
		task.execute();
	}

	@Override
	public IBinder onBind(Intent arg0) {
		return null;
	}

	private void setLoadStatus(int status) {
		SharedPreferences shardPreferences = context.getSharedPreferences(
				GROUPSBOOTRECEIVER, 0);
		int loadStatus = shardPreferences
				.getInt(GROUP_STATUS, STATE_UNIMPORTED);
		Log.d(TAG, "setLoadStatus old = " + loadStatus + " new = " + status);
		shardPreferences.edit().putInt(GROUP_STATUS, status).commit();
	}

	private int getLoadStatus() {
		SharedPreferences shardPreferences = context.getSharedPreferences(
				GROUPSBOOTRECEIVER, 0);
		int loadStatus = shardPreferences
				.getInt(GROUP_STATUS, STATE_UNIMPORTED);
		Log.d(TAG, "getLoadStatus status = " + loadStatus);
		return loadStatus;
	}

	class LoadGroupsContactsTask extends
			WeakAsyncTask<Void, Void, Void, Context> {
		public LoadGroupsContactsTask(Context context) {
			super(context);
		}

		@Override
		protected Void doInBackground(Context context, Void... params) {
			doPreSotred(context);
			return null;
		}
	}

	private void doPreStoreInternal(Context context) {
		ArrayList<String> groups = parse();
		for (int i = 0; i < groups.size(); i++) {
			actuallyPrestroeOneGroup(getContentResolver(), groups.get(i));
		}
	}

	private ArrayList<String> parse() {
		ArrayList<String> groups = new ArrayList<String>();
		XmlResourceParser parser = context.getResources().getXml(
				R.xml.default_groups);
		try {
			int eventType;
			while ((eventType = parser.next()) != XmlResourceParser.END_DOCUMENT) {
				if (eventType == XmlResourceParser.START_TAG) {
					String title = parser.getAttributeValue(null, "title");
					groups.add(title);
				}
				parser.next();
			}
		} catch (XmlPullParserException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		parser.close();
		return groups;
	}

	private void doPreSotred(Context context) {
		int import_status = getLoadStatus();
		Log.e(TAG, "doPreSotred import_status =" + import_status);
		if (import_status == STATE_UNIMPORTED) {
			Log.e(TAG, "prepare to insert groups");
			setLoadStatus(STATE_IMPORTING);
			doPreStoreInternal(context);
			Log.e(TAG, "insert groups completely");
		}
	}

	private long getInsertedGroupId(
			final ArrayList<ContentProviderOperation> diff,
			final ContentProviderResult[] results) {
		final int diffSize = diff.size();
		for (int i = 0; i < diffSize; i++) {
			ContentProviderOperation operation = diff.get(i);
			if (operation.getUri().getEncodedPath()
					.contains(Groups.CONTENT_URI.getEncodedPath())) {
				return ContentUris.parseId(results[i].uri);
			}
		}
		return -1;
	}

	private void actuallyPrestroeOneGroup(ContentResolver resolver, String title) {
		Log.e(TAG, "actuallyPrestroeOneContact 0 " + title);
		ArrayList<ContentProviderOperation> operationList = new ArrayList<ContentProviderOperation>();
		ContentProviderOperation.Builder builder = ContentProviderOperation
				.newInsert(Groups.CONTENT_URI);
		builder.withValue(Groups.TITLE, title);
		builder.withValue(Groups.NOTES, title);
		// builder.withValue(Groups.ACCOUNT_TYPE,
		// SIMContactsContract.LOCAL_ACCOUNT_TYPE);
		// builder.withValue(Groups.ACCOUNT_NAME,
		// SIMContactsContract.ACCOUNT_PRELOAD);
		builder.withValue(Groups.SHOULD_SYNC, 0);
		builder.withValue(Groups.GROUP_VISIBLE, 1);
		builder.withValue(Groups.GROUP_IS_READ_ONLY, 1);
		operationList.add(builder.build());
		try {
			ContentProviderResult[] results = resolver.applyBatch(
					ContactsContract.AUTHORITY, operationList);
			long group_id = getInsertedGroupId(operationList, results);
			Log.d(TAG, "group_id = " + group_id);
			if (group_id != 0) {
				if ("Emergency".equals(title)) {
					initDefaultEmergencyContactWithGroupId(group_id);
				} else if ("Special No".equals(title)) {
					initDefaultSpecialNoContactWithGroupId(group_id);
				}
			}
		} catch (RemoteException e) {
			Log.e(TAG, String.format("%s: %s", e.toString(), e.getMessage()));
		} catch (OperationApplicationException e) {
			Log.e(TAG, String.format("%s: %s", e.toString(), e.getMessage()));
		}
	}

	private void initDefaultEmergencyContactWithGroupId(long groupid) {
		Log.e(TAG, "initDefaultContact()");
		ContentResolver resolverPreStore = context.getContentResolver();
		Log.e(TAG, "initDefaultContact : parser == null, parse false.");
		XmlResourceParser parser = context.getResources().getXml(
				R.xml.default_emergency_names);
		try {
			int eventType = parser.getEventType();
			Log.i(TAG, "eventType = " + eventType);
			DefaultContactInfo currentContactInfo = null;
			while (eventType != XmlPullParser.END_DOCUMENT) {
				switch (eventType) {
				case XmlPullParser.START_DOCUMENT:
					break;
				case XmlPullParser.START_TAG:
					String parseName = parser.getName();
					Log.i(TAG, "parseName = " + parseName);
					if ("name".equals(parseName)) {
						String groupId = parser.getAttributeValue(null, "id");
						String name = parser.getAttributeValue(null, "name");
						currentContactInfo = new DefaultContactInfo();
						currentContactInfo.setIdStr(groupId);
						currentContactInfo.setName(name);
					} else if ("number".equals(parseName)) {
						if (currentContactInfo != null) {
							currentContactInfo.setNumber(parser.nextText());
						}
					}
					break;
				case XmlPullParser.END_TAG:
					if ("name".equals(parser.getName())) {
						if (currentContactInfo != null) {
							actuallyPrestroeOneContact(resolverPreStore,
									currentContactInfo, groupid);
						}
					}
				}
				if (eventType == XmlPullParser.END_TAG
						&& "names".equals(parser.getName())) {
					Log.e(TAG, "END_TAG ==names break.");
					break;
				}
				eventType = parser.next();
			}
		} catch (XmlPullParserException e) {
			Log.e(TAG, "Got execption while getting perferred time zone.", e);
		} catch (IOException e) {
			Log.e(TAG, "Got execption while getting perferred time zone.", e);
		}
	}

	private void initDefaultSpecialNoContactWithGroupId(long groupid) {
		Log.e(TAG, "initDefaultContact()");
		ContentResolver resolverPreStore = context.getContentResolver();
		Log.e(TAG, "initDefaultContact : parser == null, parse false.");
		XmlResourceParser parser = context.getResources().getXml(
				R.xml.default_specialno_names);
		try {
			int eventType = parser.getEventType();
			Log.i(TAG, "eventType = " + eventType);
			DefaultContactInfo currentContactInfo = null;
			while (eventType != XmlPullParser.END_DOCUMENT) {
				switch (eventType) {
				case XmlPullParser.START_DOCUMENT:
					break;
				case XmlPullParser.START_TAG:
					String parseName = parser.getName();
					Log.i(TAG, "parseName = " + parseName);
					if ("name".equals(parseName)) {
						String groupId = parser.getAttributeValue(null, "id");
						String name = parser.getAttributeValue(null, "name");
						currentContactInfo = new DefaultContactInfo();
						currentContactInfo.setIdStr(groupId);
						currentContactInfo.setName(name);
					} else if ("number".equals(parseName)) {
						if (currentContactInfo != null) {
							currentContactInfo.setNumber(parser.nextText());
						}
					}
					break;
				case XmlPullParser.END_TAG:
					if ("name".equals(parser.getName())) {
						if (currentContactInfo != null) {
							actuallyPrestroeOneContact(resolverPreStore,
									currentContactInfo, groupid);
						}
					}
				}
				if (eventType == XmlPullParser.END_TAG
						&& "names".equals(parser.getName())) {
					Log.e(TAG, "END_TAG ==names break.");
					break;
				}
				eventType = parser.next();
			}
		} catch (XmlPullParserException e) {
			Log.e(TAG, "Got execption while getting perferred time zone.", e);
		} catch (IOException e) {
			Log.e(TAG, "Got execption while getting perferred time zone.", e);
		}
	}

	private void actuallyPrestroeOneContact(ContentResolver resolver,
			DefaultContactInfo contactInfo, long groupid) {
		Log.e(TAG, "actuallyPrestroeOneContact 0 ");
		ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();
		ops.add(ContentProviderOperation
				.newInsert(ContactsContract.RawContacts.CONTENT_URI)
				.withValue(ContactsContract.RawContacts.ACCOUNT_TYPE, null)
				// .withValue(ContactsContract.RawContacts._ID, 0)
				.withValue(ContactsContract.RawContacts.ACCOUNT_NAME, null)
				.withValue(ContactsContract.RawContacts.AGGREGATION_MODE,
						ContactsContract.RawContacts.AGGREGATION_MODE_DISABLED)
				.build());
		// add name
		if (!TextUtils.isEmpty(contactInfo.getName())) {
			ops.add(ContentProviderOperation
					.newInsert(ContactsContract.Data.CONTENT_URI)
					.withValueBackReference(
							ContactsContract.Data.RAW_CONTACT_ID, 0)
					.withValue(
							ContactsContract.Data.MIMETYPE,
							ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE)
					.withValue(
							ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME,
							contactInfo.getName()).build());
		}
		// add phone
		if (!TextUtils.isEmpty(contactInfo.getNumber())) {
			ops.add(ContentProviderOperation
					.newInsert(ContactsContract.Data.CONTENT_URI)
					.withValueBackReference(
							ContactsContract.Data.RAW_CONTACT_ID, 0)
					.withValue(
							ContactsContract.Data.MIMETYPE,
							ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE)
					.withValue(ContactsContract.CommonDataKinds.Phone.NUMBER,
							contactInfo.getNumber())
					.withValue(ContactsContract.CommonDataKinds.Phone.TYPE,
							Phone.TYPE_MOBILE).build());
		}
		// add group
		if (groupid != 0) {
			ops.add(ContentProviderOperation
					.newInsert(ContactsContract.Data.CONTENT_URI)
					.withValueBackReference(
							ContactsContract.Data.RAW_CONTACT_ID, 0)
					.withValue(ContactsContract.Data.MIMETYPE,
							GroupMembership.CONTENT_ITEM_TYPE)
					.withValue(GroupMembership.GROUP_ROW_ID, groupid).build());
		}
		try {
			resolver.applyBatch(ContactsContract.AUTHORITY, ops);
		} catch (RemoteException e) {
			Log.e(TAG, String.format("%s: %s", e.toString(), e.getMessage()));
		} catch (OperationApplicationException e) {
			Log.e(TAG, String.format("%s: %s", e.toString(), e.getMessage()));
		}
	}
}
